﻿using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using Estimate.Common.Repository;
using Estimate.Common.Entity;
using Estimate.Common.DBFieldTypes;
using Estimate.Common.Estimate;

namespace Estimate.Common.DBHealth
{
   
    /// <summary>
    /// 检测预报表的问题
    /// </summary>
    public class ForeHealth
    {
        public bool CheckLackRecord = true;
        public bool CheckEmptySemi = true;
        public bool CheckRepeatStation = true;
        public bool CheckLackStation = true;
        public bool CheckAbnormalStation = true;
        public bool CheckValue = true;
        public bool CheckSemi = true;

        ForeRepository Repository = null;
        DateTime BeginDate;
        DateTime EndDate;
        ForeFactorType FactorType;
        ForeSemiType SemiType = ForeSemiType.Auto;
        //ForeDataType DataType;
        string ConnectionString;

        private Dictionary<string, int> _autoStations;
        private Dictionary<string, int> _manualStations;

        public ForeHealth()
        {
            ConnectionString = ConfigurationManager.AppSettings["ConnectionString"];

            _autoStations = new Dictionary<string, int>();
            _manualStations = new Dictionary<string, int>();
        }

        /// <summary>
        /// 检查预报数据的完整性、准确性
        /// </summary>
        /// <param name="foreDataType">预报数据类型(cityfore、sitefore、zytfore)</param>
        /// <param name="beginDate"></param>
        /// <param name="endDate"></param>
        /// <param name="semiType">评估值类型</param>
        /// <param name="foreType">天气要素类型</param>
        /// <param name="msg">返回的消息</param>
        /// <returns></returns>
        public DataTable CheckHealth(DateTime beginDate, DateTime endDate, ForeSemiType semiType, ForeFactorType factorType, string dataTable)
        {
            //DataType = dataType;
            BeginDate = beginDate;
            EndDate = endDate;
            SemiType = semiType;
            FactorType = factorType;
            Repository = new ForeRepository(ConnectionString, dataTable);

            //switch (DataType)
            //{
            //    case ForeDataType.city:
            //        Repository = ForeRepositoryFactory.NormalCityForeRepository(ConnectionString);
            //        break;
            //    case ForeDataType.site:
            //        Repository = ForeRepositoryFactory.StSiteForeRepository(ConnectionString);
            //        break;
            //    case ForeDataType.zyt:
            //        Repository = ForeRepositoryFactory.ZytCityForeRepository(ConnectionString);
            //        break;
            //}

           
            return CheckHealth();

        }

        private DataTable CheckHealth()
        {
           
            DataTable CheckResult = new DataTable();
            CheckResult.Columns.Add("说明");
            CheckResult.Columns.Add("表名");
            CheckResult.Columns.Add("日期");
            CheckResult.Columns.Add("天气要素");
            CheckResult.Columns.Add("评估值类型");
            CheckResult.Columns.Add("发报时间");
            CheckResult.Columns.Add("预报时效");
            CheckResult.DefaultView.Sort = "表名 asc,说明 asc,日期 asc,预报时效 asc";

            List<string> CheckKeys = null;

            if (FactorType == ForeFactorType.wth)
                CheckKeys = CheckForeDataKeys.GetWthCheckKeys();//CheckForeDataKeys.GetWthCheckKeys(DataType);
            else if (FactorType == ForeFactorType.maxt || FactorType == ForeFactorType.mint)
                CheckKeys = CheckForeDataKeys.GetTempCheckKeys();// CheckForeDataKeys.GetTempCheckKeys(DataType);
           
            //按日期分类
            Dictionary<DateTime, Dictionary<string, ForeEntity>> Entities = new Dictionary<DateTime, Dictionary<string, ForeEntity>>();
            DateTime cur = BeginDate;
            while (cur <= EndDate)
            {
                Entities.Add(cur, new Dictionary<string, ForeEntity>());
                cur = cur.AddDays(1);
            }

            ForeEntity[] entities = Repository.InquerySemiWithDateRange(BeginDate, EndDate, FactorType, SemiType);
            if (CheckLackRecord)
            {
                foreach (ForeEntity entity in entities)
                    Entities[entity.Date].Add(entity.Span.ToString() + "-" + entity.Sendpoint.ToString(), entity);

                foreach (KeyValuePair<DateTime, Dictionary<string, ForeEntity>> pair in Entities)
                {
                    if (pair.Value.Count == CheckKeys.Count)
                        continue;
                    foreach (string key in CheckKeys)
                        if (!pair.Value.ContainsKey(key))
                        {
                            string[] strs = key.Split('-');
                            CheckResult.Rows.Add(new object[] { "缺少记录", Repository.TableName, pair.Key.ToString("yyyy-MM-dd"), FactorType, SemiType, strs[1], strs[0] });
                        }
                }
            }
            
            foreach (ForeEntity entity in entities)
            {
                if (entity.Semi.Length <= 5)
                {
                    if (CheckEmptySemi)
                        CheckResult.Rows.Add(new object[] { "空Semi", Repository.TableName, entity.Date.ToString("yyyy-MM-dd"), entity.Type, entity.Semitype, entity.Sendpoint, entity.Span });
                }
                else
                {
                    if (CheckValue)
                    {
                        ResetSemiStations(entity.Semitype);
                        CheckData("value", entity.Value, entity, CheckResult);
                    }
                    if (CheckSemi)
                    {
                        ResetSemiStations(entity.Semitype);
                        CheckData("semi", entity.Semi, entity, CheckResult);//semi是不会丢站的。因为semi中预先多存了
                    }
                }
            }

            return CheckResult;

        }

        private void ResetSemiStations(ForeSemiType semitype)
        {
            RealStationCompareRepository repository = new RealStationCompareRepository(ConfigurationManager.AppSettings["ConnectionString"]);

            Dictionary<string, int> stations;
            if (semitype == ForeSemiType.Auto)
                stations = _autoStations;
            else
                stations = _manualStations;

            if (stations.Count == 0)
            {
                ForeRealStationCompareEntity[] entitys = repository.GetAllRecord(GetCompareType(semitype));
                foreach (ForeRealStationCompareEntity entity in entitys)
                    stations[entity.ForeStation] = 0;
            }
            else
            {

                Dictionary<string, int> newStations = new Dictionary<string, int>();
                foreach (string key in stations.Keys)
                    newStations[key] = 0;

                if (semitype == ForeSemiType.Auto)
                    _autoStations = newStations;
                else
                    _manualStations = newStations;

            }
        }

        public bool CheckData(string name, string value, ForeEntity entity, DataTable CheckResult)
        {
            bool result = true;

            string[] ss = value.Split('|');
            foreach (string s in ss)
            {
                if (s.Length < 5)
                    continue;
                string station = s.Substring(0, 5);
                bool r = FindStation(entity.Semitype, station, name);
                if (r == false && CheckAbnormalStation)
                    CheckResult.Rows.Add(new object[] { string.Format("{0}中出现非常站点{1}", name, station), Repository.TableName, entity.Date.ToString("yyyy-MM-dd"), entity.Type, entity.Semitype, entity.Sendpoint, entity.Span });

            }
            List<string> more;
            List<string> miss;
            CheckStations(entity.Semitype, out more, out miss);
            if (more.Count > 0)
            {
                result = false;
                string r = string.Join(",", more);
                if (CheckRepeatStation)
                    CheckResult.Rows.Add(new object[] { string.Format("{0}中多次出现站号为{1}的记录", name, r), Repository.TableName, entity.Date.ToString("yyyy-MM-dd"), entity.Type, entity.Semitype, entity.Sendpoint, entity.Span });
            }

            if (miss.Count > 0)
            {
                result = false;
                string r = string.Join(",", miss);
                if (CheckLackStation)
                    CheckResult.Rows.Add(new object[] { string.Format("{0} 丢失站 {1}", name, r), Repository.TableName, entity.Date.ToString("yyyy-MM-dd"), entity.Type, entity.Semitype, entity.Sendpoint, entity.Span });
            }

            return result;
        }

       
        private bool FindStation(ForeSemiType foreSemiType, string station, string name)
        {
            bool result = true;

            Dictionary<string, int> stations;
            if (foreSemiType == ForeSemiType.Auto)
                stations = _autoStations;
            else
                stations = _manualStations;
        
            if (stations.ContainsKey(station))
                stations[station] += 1;
            else
                result = false;
 
            return result;
        }

        private void CheckStations(ForeSemiType foreSemiType, out List<string> more, out List<string> miss)
        {
            more = new List<string>();
            miss = new List<string>();

            Dictionary<string, int> stations;
            if (foreSemiType == ForeSemiType.Auto)
                stations = _autoStations;
            else
                stations = _manualStations;

            foreach (KeyValuePair<string, int> pair in stations)
            {
                if (pair.Value == 0)
                    miss.Add(pair.Key);

                if (pair.Value > 1)
                    more.Add(pair.Key);
            }

            //Dictionary<string, int> newStations = new Dictionary<string, int>();
            //foreach (string key in stations.Keys)
            //    newStations[key] = 0;

            //if (foreSemiType == ForeSemiType.Auto)
            //    _autoStations = newStations;
            //else
            //    _manualStations = newStations;

        }

     
        public  RealStationCompareType GetCompareType(ForeSemiType semitype)
        {
            if (semitype == ForeSemiType.Auto)
                return RealStationCompareType.Normal_Auto;
            else
                return RealStationCompareType.Normal_Manual;

            //if (DataType == ForeDataType.city)
            //{
            //    if (semitype == ForeSemiType.Auto)
            //        return RealStationCompareType.Normal_Auto;
            //    else
            //        return RealStationCompareType.Normal_Manual;
            //}
            //else if (DataType == ForeDataType.site)
            //{
            //    if (semitype == ForeSemiType.Auto)
            //        return RealStationCompareType.Site_Auto;
            //    else
            //        return RealStationCompareType.Site_Auto;
            //}
            //else if (DataType == ForeDataType.zyt)
            //{
            //    if (semitype == ForeSemiType.Auto)
            //        return RealStationCompareType.Normal_Auto;
            //    else
            //        return RealStationCompareType.Normal_Manual;
            //}

            return RealStationCompareType.None;
        }


    }
}
